package impl;

import java.util.ArrayList;

import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import javax.ejb.EJB;
import javax.ejb.Schedule;
import javax.ejb.Stateless;
import javax.ejb.TransactionAttribute;
import javax.ejb.TransactionAttributeType;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;


import org.jboss.logging.Logger;

import p3_entities.Friend;
import p3_entities.Messageboard;
import p3_entities.Usermessage;
import p3_entities.Userphoto;
import p3_entities.Userprofile;

import api.InvalidAuthenticationException;
import api.ejb.IAuthenticator;
import api.ejb.IMessages;
import api.ejb.IPostman;


/**
 * Session Bean implementation class Socializer
 */
@Stateless(name = "IMessages")
//@TransactionAttribute(value = TransactionAttributeType.REQUIRES_NEW)
public class Messages implements IMessages {
	@PersistenceContext(unitName = "PhaseBookPU")
	EntityManager em;
	
	@EJB(beanName = "IPostman")
	IPostman postman;

	private static final Logger log = Logger.getLogger(Messages.class);


	static final long MILLIS_IN_A_DAY = 1000 * 60 * 60 * 24;

	/**
	 * Default constructor.
	 */
	public Messages() {
		// TODO Auto-generated constructor stub
	}

	

	@Override
	public boolean publishPublicMessage(int ownerId, int posterId,
			String message, int photoId) throws InvalidAuthenticationException {

		log.info("Executing ---------->");

		Messageboard msgBoard = getMessageBoard(ownerId,
				MessageBoardsType.PUBLIC);
		if (msgBoard == null)
			return false;

		Userprofile posterUser = em.find(Userprofile.class, posterId);
		
		boolean b = publishUserMessage(msgBoard, posterUser, message, photoId);
		log.info("<--------------- Done");

		return b;

	}

	@Override
	public boolean publishPrivateMessage(int ownerId, int posterId,
			String message, int photoId) {
		log.info("Executing ---------->");


		if (ownerId != posterId) 
				//&& (	!isFriendWith(ownerId, posterId)))
		{
			
			return false;
		}

		Messageboard msgBoard = getMessageBoard(ownerId,
				MessageBoardsType.PRIVATE);
		if (msgBoard == null)
			return false;

		Userprofile posterUser = em.find(Userprofile.class, posterId);

		boolean b = publishUserMessage(msgBoard, posterUser, message, photoId);
		
		log.info("<--------------- Done");

		
		return b;

	}

	@Override
	public List<Usermessage> getPublicMessageList(int uid) {
		log.info("Executing ---------->");	

		List<Usermessage> l = getUserBoardMessage(uid, MessageBoardsType.PUBLIC);
		
		log.info("<--------------- Done");

		return l;
	}

	@Override
	public List<Usermessage> getPrivateMessageList(int uid) {
		log.info("Executing ---------->");	

		List<Usermessage> l = getUserBoardMessage(uid, MessageBoardsType.PRIVATE);
		
		log.info("<--------------- Done");
		
		return l;
	}

	
	public Map getDigestDayilyUserMessages() {

		log.info("Executing ---------->");	


		Query query = em.createNamedQuery("getDailyMessages");

		Date yesterday = new Date(new java.util.Date().getTime()
				- MILLIS_IN_A_DAY);
		query.setParameter("yesterday", yesterday);

		List<Usermessage> messages = query.getResultList();

		log.info("There are "+messages.size()+" elegible messages.");	

		HashMap<Integer, List<Usermessage>> hash = new HashMap<Integer, List<Usermessage>>();

		for (Usermessage m : messages) {

			if (!m.getUserboard().getUserprofile().getNotify_Digest())
				continue;

			Integer uid = m.getUserboard().getUserprofile().getUserId();
			List<Usermessage> mappedML = hash.get(uid);
			if (mappedML == null) {
				ArrayList<Usermessage> mu = new ArrayList<Usermessage>();
				mu.add(m);
				hash.put(uid, mu);
			} else {
				mappedML.add(m);
			}
		}

		HashMap<Integer, String> emails = new HashMap<Integer, String>();
		
		for (Entry<Integer, List<Usermessage>> entry : hash.entrySet()) {
			Integer uid = entry.getKey();
			messages = entry.getValue();
			StringBuffer buf = new StringBuffer();

			buf.append("Hello again from PhaseBook");
			buf.append("\n\n");
			buf.append("Here is what happened today: ");
			buf.append("\n");

			for (Usermessage message : messages) {

				buf.append("-------------------------\n");
				buf.append("From: ");
				buf.append(message.getUserprofile1().getName());
				buf.append("\n");

				buf.append(message.getTextMessage());
				buf.append("\n");
				buf.append("Posted On: ");
				buf.append(message.getPostedOn().toString());

				buf.append("\n-------------------------\n\n\n");

			}
			
			emails.put(uid, buf.toString());			

		}
		
		log.info("There are "+emails.size()+" users to be notified.");	

		log.info("<--------------- Done");

		return emails;

		
	}

	private Messageboard getMessageBoard(int uid, MessageBoardsType type) {

		log.info("Executing ---------->");	

		Query query = em.createNamedQuery("getUserMessageBoard");
		query.setParameter("userId", uid);
		query.setParameter(1, type.ordinal());
		Messageboard b = (Messageboard) query.getSingleResult();
		
		log.info("<--------------- Done");
		
		return b;

	}

	private boolean publishUserMessage(Messageboard msgBoard,
			Userprofile posterUser, String message, int photoId) {

		log.info("<--------------- Done");

		// Create a user message board
		Usermessage userMessage = new Usermessage();
		userMessage.setUserprofile1(posterUser);
		userMessage.setUserboard(msgBoard);

		if (message != null)
			userMessage.setTextMessage(message);

		if (photoId != 0) {
			Userphoto userPhoto = em.find(Userphoto.class, photoId);
			userMessage.setPhotoId(userPhoto);
		}

		userMessage.setPostedOn(new Date());

		em.persist(userMessage);

		if (msgBoard.getUserprofile().getNotify_OnChange()) {

			String emailMessage = "Hi " + msgBoard.getUserprofile().getEmail()
					+ "\n\n" + "You have a new message from '"
					+ posterUser.getEmail() + "'";
			
			postman.sendMail(msgBoard.getUserprofile().getEmail(), "You have a new message!", emailMessage);
		}


		
		log.info("<--------------- Done");

		return true;

	}

	private List<Usermessage> getUserBoardMessage(int uid,
			MessageBoardsType type) {
		log.info("<--------------- Done");


		Query query = em.createNamedQuery("getUserBoardMessages");
		query.setParameter("userId", uid);
		query.setParameter(1, type.ordinal());
		
		log.info("<--------------- Done");


		return query.getResultList();

	}
}
